import {
  ACCESS_TOKEN_KEY,
  IAM_AUTHORIZE_URL,
  IAM_LOGOUT_URL,
  USER_ID_KEY
} from 'constants/index';
import qs from 'qs';
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';

import { IUserinfo, auth0State, userState } from 'state/auth0State';
import { projectSettingsState } from 'state/project';
import { httpEndpoint } from "api/index"

export function useAuth0() {
  const auth0 = useRecoilValue(auth0State);
  const user = useRecoilValue(userState);

  function loginWithRedirect(options: Record<string, any>) {
    location.href = `${IAM_AUTHORIZE_URL}${qs.stringify(options, {
      addQueryPrefix: true
    })}`;
  }

  function getAccessTokenSilently(_: {
    authorizationParams: Record<string, any>;
  }) {
    return Promise.resolve(auth0.accessToken);
  }

  async function logout(options: {
    logoutParams: {
      returnTo: string;
      [key: string]: any;
    };
  }) {
    localStorage.removeItem(ACCESS_TOKEN_KEY);
    localStorage.removeItem(USER_ID_KEY);
    location.href = `${IAM_LOGOUT_URL}?redirect_uri=${options.logoutParams.returnTo}`;
  }

  return {
    user,
    isAuthenticated: auth0.isAuthenticated,
    isLoading: auth0.isLoading,
    error: auth0.error,
    loginWithRedirect,
    getAccessTokenSilently,
    logout
  };
}

export interface IAuth0ProviderProps {
  domain?: string;
  clientId?: string;
  authorizationParams: {
    redirect_uri?: string;
  };
  useRefreshTokens?: boolean;
  cacheLocation?: string;
  children: JSX.Element;
}

export function Auth0Provider(props: IAuth0ProviderProps) {
  const { children } = props;
  const projectSettings = useRecoilValue(projectSettingsState);
  const auth0 = useRecoilValue(auth0State);
  const setUserState = useSetRecoilState(userState);

  useEffect(() => {
    const accessToken = auth0.accessToken;
    const userId = auth0.userId;
    if (accessToken && userId && projectSettings?.chainlitServer) {
      // `${httpEndpoint}/api/me?userId=${userId}`
      fetch(`${httpEndpoint}/api/me`, {
        headers: {
          Authorization: accessToken
        },
        method: 'GET'
      })
        .then((res: Response) => {
          return res.ok ? res.json() : null;
        })
        .then((res: IUserinfo) => {
          setUserState(res);
        })
        .catch(() => {
          return null;
        });
    }
  }, [projectSettings, auth0]);

  return <>{children}</>;
}
